import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import java.util.Iterator;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Writer;
import java.io.BufferedWriter;
import java.io.IOException;

/**
 * This class, contains the necessary methods to work with a dictionary file.
 * 
 * @author Tom Castle
 * @version v.0.01 16/02/04
 */
public class Dictionary
{
    /*public static void main(String[] args)
	{
	    Dictionary myDict = new Dictionary("EnglishFull.txt");
	}*/
    
    private TreeSet dict;
    private String filename;
    
    /**
     * Constructor for objects of class Dictionary
     */
    public Dictionary()
    {
        filename = "English.txt";
        
        dict = new TreeSet();
        buildDictFromFile();
    }
    
    /**
     * Constructor for objects of class Dictionary - filename specified
     */
    public Dictionary(String filename)
    {
        this.filename = filename;
        dict = new TreeSet();
        buildDictFromFile();
    }
    
    /**
     * Constructor for objects of class Dictionary - filename specified
     */
    public Dictionary(File file)
    {
        this.filename = file.getPath();
        dict = new TreeSet();
        buildDictFromFile();
    }    
    

    /**
     * Get the pattern set for one word, from the dict.
     * 
     * @param   String - The word to find pattern set of.
     * @return  ArrayList of pattern set.
     */
    public ArrayList getPatternSet(String cWord)
    {
        String dWord;
        ArrayList patternSet = new ArrayList();
        Iterator it = dict.iterator();
        while(it.hasNext()){    //for each word in dict
            dWord = (String) it.next();
            if (match(dWord, cWord)) patternSet.add(dWord); //if cipherword and dict word match, insert in pattern set.
        }
        return patternSet;
    }
    
    /**
     * Tests match between two words.
     * 
     * @return true if matching pattern, else false.
     */    
    private boolean match(String W1, String W2)
    {
        int w1Len = W1.length();
        if (w1Len != W2.length()) return false;
        for (int i=1; i<w1Len; i++){
            char w1Chari = W1.charAt(i);
            char w2Chari = W2.charAt(i);
            for (int j=0; j<(i-1); j++){
                if ((w1Chari == W1.charAt(j)) != (w2Chari == W2.charAt(j))) return false;
            }
        }
        return true;
    }

    /**
     * Reads in each line of dictionary text file, and converts to ArrayList. 
     * 
     * @return     the dictionary ArrayList of words
     */
    public TreeSet buildDictFromFile()
    {
        //clear old dictionary ArrayList.
        dict.clear();
        BufferedReader reader;
        
        File file = new File(filename);
        file = file.getAbsoluteFile();
        
        try {
            reader = new BufferedReader(
                new FileReader(file));
            //for each line of the dictionary text file, read into arraylist.
            while(reader.ready()){
                dict.add(reader.readLine().toUpperCase().trim());
            }
            reader.close();
        }
        catch(IOException e)
        {
            //fail quietly
            //System.out.println("Unable to open file: " + filename);
            //System.out.println("Program ended...");
        }
        //dict = removeDupes(dict);
        //printToFile(dict,file);
        return dict;
    }
    
    /**
     * Prints out the dictionary into a new text file of given name.
     */
    private void printToFile(TreeSet data, File file)
    {
        try {
            //use buffering
            Writer output = new BufferedWriter(new FileWriter(file));
            String newline = System.getProperty("line.separator"); //for platform independence.
            Iterator it = data.iterator();
            while(it.hasNext()){
                output.write((String) it.next() + newline);
            }
            output.close();
        }catch(IOException e){
            System.err.println("IOException occured when writing to file " + file.getName() + ": " + e);
        }
    }
    
    
    /**
     * Removes the duplicates from a given list, and returns the new list.
     */
    private TreeSet removeDupes(TreeSet words)
    {
        Iterator it = words.iterator();
        while (it.hasNext()){
            String word = (String) it.next();
            if (((List) words).indexOf(word) != ((List) words).lastIndexOf(word)){
                it.remove();
            }
        }
        return words;
    }
    
    /**
     * Tests whether the dictionary contains a word, returns true if it does
     * otherwise false.
     */
    public boolean containsWord(String word)
    {
        return dict.contains(word);
    }
}
